package cc.linker.steplink.crm.service.impl;

import cc.linker.steplink.crm.commons.Constants;
import cc.linker.steplink.crm.commons.MongoDBConstants;
import cc.linker.steplink.crm.commons.RandomCodeGenerator;
import cc.linker.steplink.crm.commons.RedisConstants;
import cc.linker.steplink.crm.commons.enums.IntegralEnums;
import cc.linker.steplink.crm.commons.http.HttpService;
import cc.linker.steplink.crm.commons.model.SystemProperties;
import cc.linker.steplink.crm.commons.utils.MD5;
import cc.linker.steplink.crm.commons.yzj.YzjRequest;
import cc.linker.steplink.crm.dao.*;
import cc.linker.steplink.crm.domain.*;
import cc.linker.steplink.crm.merchant.util.Global;
import cc.linker.steplink.crm.merchanth5.service.CustomerIntegralService;
import cc.linker.steplink.crm.merchanth5.service.VipCustomerLogService;
import cc.linker.steplink.crm.response.GlobalException;
import cc.linker.steplink.crm.service.ICustomerBindService;
import cc.linker.steplink.crm.service.ISyncService;
import cc.linker.steplink.crm.service.IUserService;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.mongodb.util.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;

import java.io.IOException;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * idp同步
 */
@EnableAsync
@Service
@Slf4j
public class SyncServiceImpl implements ISyncService {

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private SyncDao syncDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private CustomerDao customerDao;
    @Autowired
    private CustomerInfoDao customerInfoDao;
    @Autowired
    private CustomerInfoIdpDao customerInfoIdpDao;
    @Autowired
    private ICustomerBindService customerBindService;
    @Autowired
    private HttpService httpService;
    @Autowired
    private SystemProperties systemProperties;
    @Value("${yzj.orgId}")
    private String yzjOrgId;
    @Autowired
    private CustomerIntegralService customerIntegralService;
    @Autowired
    private ScoreLogDao scoreLogDao;
    @Autowired
    private YzjRequest yzjRequest;
    @Autowired
    private PersonalCenterDao personalCenterDao;

    @Autowired
    private IUserService userService;
    @Autowired
    private VipCustomerLogService vipCustomerLogService;
    @Autowired
    private ActionLogDao actionLogDao;

    /**
     * @Modify: wuyue
     * @Date: 2019/9/10 13:16
     * @Description: 用户关注状态
     * @Version: v1.0.x
     */
    @Override
    public void analyse(Map<String, Object> idpInfo) throws IOException, URISyntaxException {
        String idpId = idpInfo.get("idpId").toString();

        String idpName = (String) idpInfo.get("idpName");
        String idpBindCustomerCode = (String) idpInfo.get("idpBindCustomerCode");
        String idpAddress = (String) idpInfo.get("idpAddress");
        String idpArea = (String) idpInfo.get("idpArea");
        String idpAvatar = (String) idpInfo.get("idpAvatar");
//        String idpCompany = (String) idpInfo.get("idpCompany");
        String idpEmail = (String) idpInfo.get("idpEmail");
        String idpFax = (String) idpInfo.get("idpFax");
        String idpGender = (String) idpInfo.get("idpGender");
        String idpOpenid = (String) idpInfo.get("idpOpenid");
        String idpRemark = (String) idpInfo.get("idpRemark");
        //文档拼写错误
        String idpToken = (String) idpInfo.get("ipdToken");
        String idpOrgId = (String) idpInfo.get("idpOrgId");
        String channel = (String) idpInfo.get("channel");
        String nickName = (String) idpInfo.get("nickName");
        String idpPhone;
        Object idpPhones = idpInfo.get("idpPhone");
        if (idpPhones == null) {
            idpPhone = "";
        } else if (idpPhones instanceof String) {
            idpPhone = (String) idpPhones;
        } else if (idpPhones instanceof List) {
            idpPhone = (String) ((List) idpPhones).get(0);
        } else {
            idpPhone = "";
        }

        idpOrgId = idpOrgId == null ? "" : idpOrgId;

        List idpLabels = (List) idpInfo.get("idpLabels");
        List ext = (List) idpInfo.get("ext");
        if (StringUtils.isEmpty(idpOrgId) && !StringUtils.isEmpty(idpToken)) {
            idpOrgId = getOrgCodeByToken(idpToken);
        }

        // 基础信息
        Customer customer = new Customer();
        customer.setSubscribe(1);
        customer.setCustomerName(StringUtils.isEmpty(idpName) ?
                (StringUtils.isEmpty(nickName) ? "" : nickName) : idpName);
        customer.setCustomerPhone(idpPhone == null ? "" : idpPhone);
        customer.setCustomerAvatar(idpAvatar == null ? "" : idpAvatar);
        customer.setOrgId(idpOrgId);
        // 目前是授权关联id，不做处理
        customer.setAdminId("");
//        if  (!StringUtils.isEmpty(idpBindCustomerCode)) {
//            User user = userDao.getSimpleUser(idpBindCustomerCode);
//            if (user != null) {
//                customer.setAdminId(user.getAdminId());
//            } else {
//                customer.setAdminId("");
//            }
//        } else {
//            customer.setAdminId("");
//        }
        // 扩展信息
        CustomerInfo customerInfo = new CustomerInfo();
        customerInfo.setCustomerAddress(idpAddress == null ? "" : idpAddress);
//        customerInfo.setCustomerCompany(idpCompany == null ? "" : idpCompany);
        /**
         * @Modify: wuyue
         * @Date: 2019/9/24 10:02
         * @Description: 不要机构名称 值为空
         * @Version: v1.9.1
         */
//        String companyName = "";
//        Map<String, Object> map = new HashMap<>();
//        map.put("action", "getOrgInfo");
//        map.put("orgcode", idpOrgId);
//        try {
//            String s = httpService.doGet(systemProperties.getUserCenter() + "WebAPI/BaseInfo.aspx", map);
//            Map parse = (Map) JSON.parse(s);
//            if (parse.containsKey("OrgName")) {
//                companyName = parse.get("OrgName").toString();
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//            LOGGER.error("用户中心信息获取失败,User Center Information Acquisition Failure");
//        }
//        customerInfo.setCustomerCompany(companyName);
        customerInfo.setCustomerFax(idpFax == null ? "" : idpFax);
        // CustomerArea 用openid 和token 调矩阵接口获得
        Map<String, Object> wxRequset = new HashMap<>();
        wxRequset.put("action", "getWeixinUserInfo");
        wxRequset.put("openid", idpOpenid);
        wxRequset.put("token", idpToken);
        String res = httpService.doPost(systemProperties.getWxpushurl(), JSON.serialize(wxRequset));
        Map parse = (Map) JSON.parse(res);
        if (parse.containsKey("data") && parse.get("data") instanceof Map) {
            Map data = (Map) parse.get("data");
            String city = data.get("city").toString();
            String province = data.get("province").toString();
            customerInfo.setCustomerArea(province + "@" + city);
        }
        CustomerInfoIdp idp = new CustomerInfoIdp();
        idp.setIdpId(idpId);
        idp.setIdpAddress(idpAddress == null ? "" : idpAddress);
        idp.setIdpEmail(idpEmail == null ? "" : idpEmail);
        idp.setIdpGender("男".equals(idpGender) ? 1 : ("女".equals(idpGender) ? 0 : 2));
        idp.setIdpName(idpName == null ? "" : idpName);
        idp.setIdpRemark(idpRemark == null ? "" : idpRemark);
        idp.setIdpPhone(idpPhone);
        idp.setIdpAvatar(idpAvatar);
        idp.setIdpOpenid(idpOpenid);
        idp.setIdpToken(idpToken);
        idp.setIdpArea(idpArea);
        idp.setOrgId(idpOrgId);

        // find by idpId
        Criteria criteria = new Criteria();
        criteria.andOperator(Criteria.where("idpId").is(idpInfo.get("idpId")));
        Map idpUser = mongoTemplate.findOne(Query.query(criteria), Map.class, MongoDBConstants.IDP_INFO_COLLECTION);
        CustomerInfoIdp idpMysql = customerInfoIdpDao.selectByPrimaryKey(idpId);
        String customerId;
        if (idpMysql == null) {
            // 判断是否有已同步的用户
            Customer oneCustomer = null;
            if (!StringUtils.isEmpty(idpOpenid) && !StringUtils.isEmpty(idpToken)) {
                customer.setWxOpenid(idpOpenid);
                customer.setWxToken(idpToken);
                oneCustomer = syncDao.findCustomerByOpenidAndToken(idpOpenid, idpToken);
            }

            if (oneCustomer != null) {
                customerId = oneCustomer.getCustomerId();

                // 如果之前内容库用户无机构，更新机构信息
                if (StringUtils.isEmpty(oneCustomer.getOrgId())) {
                    syncDao.updateCustomerByCustomerId(customerId, idpOrgId);
                }

                // idp信息持久化
                idp.setCustomerId(customerId);
                Integer insert = customerInfoIdpDao.insert(idp);

            } else {
                // 需要添加新用户
                customerId = RandomCodeGenerator.getCustomerId(Constants.CUSTOMER_CODE_SOURCE_IDP);
                customer.setCustomerId(customerId);
                customer.setCreateUser("IDP");
                customer.setCustomerSourceChannel(Byte.valueOf("1"));
                LOGGER.info("保存idp用户到客户表,客户id[{}],客户idpId[{}],机构[{}],客服编码[{}]",
                        customerId, idpId, idpOrgId, idpBindCustomerCode);
                Integer addCustomer = syncDao.addCustomer(customer);
                if (addCustomer == 1) {
                    LOGGER.info("客户id[{}]扩展信息保存", customerId);
                    customerInfo.setCustomerInfoId(UUID.randomUUID().toString());
                    customerInfo.setCustomerId(customerId);
                    Integer addCustomerInfo = syncDao.addCustomerInfo(customerInfo);

                    // idp信息持久化
                    idp.setCustomerId(customerId);
                    Integer insert = customerInfoIdpDao.insert(idp);
                } else {
                    return;
                }
            }
        } else {
            // 获取用户id
            customerId = idpMysql.getCustomerId();

            // idp信息持久化更新
            idp.setCustomerId(customerId);
            Integer update = customerInfoIdpDao.updateByPrimaryKeySelective(idp);
        }

        //  添加标签
        idpOrgId = idpOrgId == null ? "" : idpOrgId;
        saveLabels(customerId, idpOrgId, idpLabels);

        //  缓存查询idp典表，封装idp信息
        List<KeyNameValue> attributes = new ArrayList<>();
        // 获取数据库字典配置的idp键名描述信息
        Set<Object> names = stringRedisTemplate.opsForHash().keys(RedisConstants.CRM_IDP_NAME_DICT);
        if (names != null && !names.isEmpty()) {
            matchName("idpName", idpName, names, attributes);
            matchName("idpAddress", idpAddress, names, attributes);
            matchName("idpArea", idpArea, names, attributes);
            matchName("idpEmail", idpEmail, names, attributes);
            matchName("idpGender", idpGender, names, attributes);
            matchName("idpPhone", idpPhone, names, attributes);
            matchName("idpRemark", idpRemark, names, attributes);
            matchName("channel", channel, names, attributes);
            matchName("nickName", nickName, names, attributes);

            ext.forEach(item -> {
                Map<String, Object> o = (Map<String, Object>) item;
                String key = (String) o.get("key");
                String desc = (String) o.get("desc");
                List value = (List) o.get("value");

                if (names.contains(key)) {
                    String name = (String) stringRedisTemplate.opsForHash().get(RedisConstants.CRM_IDP_NAME_DICT, key);
                    if (!StringUtils.isEmpty(name) && value != null && !value.isEmpty()) {
                        attributes.add(new KeyNameValue(key, name, value.toArray()));
                    }
                }
            });
        } else {
            List<Map<String, Object>> idpNamesDict = syncDao.findIdpNamesDict();
            Map<String, String> namespace = new HashMap<>();
            idpNamesDict.forEach(i -> {
                namespace.put((String) i.get("IDPKEY"), (String) i.get("IDPNAME"));
            });
            namespace.forEach((k, v) -> stringRedisTemplate.opsForHash().put(RedisConstants.CRM_IDP_NAME_DICT, k, v));

            if (!StringUtils.isEmpty(idpName)) {
                attributes.add(new KeyNameValue("idpName", namespace.get("idpName"), new String[]{idpName}));
            }
            if (!StringUtils.isEmpty(idpAddress)) {
                attributes.add(new KeyNameValue("idpAddress", namespace.get("idpAddress"), new String[]{idpAddress}));
            }
            if (!StringUtils.isEmpty(idpArea)) {
                attributes.add(new KeyNameValue("idpArea", namespace.get("idpArea"), new String[]{idpArea}));
            }
            if (!StringUtils.isEmpty(idpEmail)) {
                attributes.add(new KeyNameValue("idpEmail", namespace.get("idpEmail"), new String[]{idpEmail}));
            }
            if (!StringUtils.isEmpty(idpGender)) {
                attributes.add(new KeyNameValue("idpGender", namespace.get("idpGender"), new String[]{idpGender}));
            }
            if (!StringUtils.isEmpty(idpPhone)) {
                attributes.add(new KeyNameValue("idpPhone", namespace.get("idpPhone"), new String[]{idpPhone}));
            }
            if (!StringUtils.isEmpty(idpRemark)) {
                attributes.add(new KeyNameValue("idpRemark", namespace.get("idpRemark"), new String[]{idpRemark}));
            }
            if (!StringUtils.isEmpty(channel)) {
                attributes.add(new KeyNameValue("channel", namespace.get("channel"), new String[]{channel}));
            }
            if (!StringUtils.isEmpty(nickName)) {
                attributes.add(new KeyNameValue("nickName", namespace.get("nickName"), new String[]{nickName}));
            }
            ext.forEach(item -> {
                Map<String, Object> o = (Map<String, Object>) item;
                String key = (String) o.get("key");
                String desc = (String) o.get("desc");
                List value = (List) o.get("value");
                if (namespace.containsKey(key) && value != null && !value.isEmpty()) {
                    attributes.add(new KeyNameValue(key, namespace.get(key), value.toArray()));
                }
            });
        }
        idpInfo.put("attributes", attributes);

        //  更新mongo，记录当前用户CUSTOMER_ID
        if (idpUser == null) {
            LOGGER.info("添加idp用户[{}]到mongodb", customerId);
            idpInfo.put("customerId", customerId);
            mongoTemplate.insert(idpInfo, MongoDBConstants.IDP_INFO_COLLECTION);
        } else {
            LOGGER.info("更新mongodb中idp用户[{}]", customerId);
            Update updateIdpUser = new Update();
            idpInfo.forEach((k, v) -> updateIdpUser.set(k, v));
            mongoTemplate.updateMulti(Query.query(criteria).addCriteria(Criteria.where("customerId").is(customerId)),
                    updateIdpUser, idpInfo.getClass(), MongoDBConstants.IDP_INFO_COLLECTION);
        }

    }

    @Override
    public void syncIdpUserAction(Map<String, Object> data) {
        String idpId = data.get("id").toString();

        String actionType = data.get("actionType").toString();
        String actionTime = data.get("actionTime").toString();
        String openid = (String) data.get("openid");
        String token = (String) data.get("token");
        String orgId = (String) data.get("orgId");


        if (!StringUtils.isEmpty(idpId) && !StringUtils.isEmpty(actionType) && !StringUtils.isEmpty(actionTime)) {
            Action action = new Action();
            action.setActionId(UUID.randomUUID().toString());
            action.setIdpId(idpId);
//            CustomerInfoIdp customer = customerInfoIdpDao.selectByPrimaryKey(idpId);

            String customerId = customerDao.selectCustomerIdByOpenIdAndToken(openid, token);
            if (!StringUtils.isEmpty(customerId)) {
                action.setCustomerId(customerId);
            } else {
                LOGGER.warn("行为无对应用户");
                return;
            }
            Integer type = Integer.valueOf(actionType);// 行为类型
            Date date = new Date(Long.valueOf(actionTime));
            String remark;
            switch (type) {
                case 1:
                    action.setActionTalkTime(date);
                    remark = "用户发起了一个对话";
                    break;
                case 2:
                    action.setActionFollowTime(date);
                    remark = "用户关注公众号";
                    break;
                case 4:
                    remark = "客服主动发起了一个对话";
                    break;
                default:
                    LOGGER.warn("未知行为类型");
                    return;
            }
            // 行为记录
            ActionLog log = new ActionLog(customerId, UUID.randomUUID().toString(), date, type, remark);
            action.setOpenid(openid == null ? "" : openid);
            action.setToken(token == null ? "" : token);
            syncDao.saveActionLog(log);
            if (type != 4) {// 此行为为最近记录，每个用户一条
                syncDao.saveIdpAction(action);
            }
        } else {
            LOGGER.warn("idp用户行为同步不包含id等关键信息");
        }
    }

    /**
     * customer表
     *
     * @param customerName    姓名
     * @param customerPhone   手机
     * @param customerEmail   邮箱
     * @param customerAvatar  头像
     * @param orgId           机构id
     *                        以下info表
     * @param customerCompany 公司
     * @param customerFax     传真
     * @param customerAddress 地址:详细地址
     * @param province        省
     * @param city            市
     * @param district        区
     */
    @Override
    public String third(Map<String, Object> map) throws GlobalException {
        if (!map.containsKey("customerName") || StringUtils.isEmpty(map.get("customerName"))) {
            throw GlobalException.build("参数不正确");
        }
        String customerId = RandomCodeGenerator.getCustomerId("E");
        map.put("customerId", customerId);
        String customerInfoId = UUID.randomUUID().toString();
        map.put("customerInfoId", customerInfoId);
        //@param customerArea = province@city@district   区域:中国@浙江@杭州
        Object province = map.get("province");
        Object city = map.get("city");
        Object district = map.get("district");
        String customerArea = "";
        if (!StringUtils.isEmpty(province) && !StringUtils.isEmpty(city) && !StringUtils.isEmpty(district)) {
            customerArea = province + "@" + city + "@" + district;
        }
        map.put("customerArea", customerArea);
        if (!StringUtils.isEmpty(map.get("sourceUserId"))) {
            String orgId = yzjOrgId;
            map.put("orgId", orgId);
            String customerIdO = customerDao.getUserCount(map);
            if (!StringUtils.isEmpty(customerIdO)) {
                map.put("customerId", customerIdO);
                customerInfoDao.updateMapSelective(map);
            } else {
                //先判断原来是否有绑定相同手机号的(有的话返回渠道和customerId)
                Map customerOld = customerDao.getOldCustomer(map);
                if (customerOld != null && customerOld.get("source") != null) {
                    customerOld.put("orgId", orgId);
                    String source = customerOld.get("source").toString();
                    String newSource = "8";
                    if (!StringUtils.isEmpty(map.get("source"))) {
                        newSource = map.get("source").toString();
                    }
                    if (!newSource.equals(source)) {
                        //查询下之前的帐号有没有多渠道
                        String oldSource = customerDao.getOldCustomerSource(customerOld);
                        if (StringUtils.isEmpty(oldSource)) {
                            //插入
                            customerOld.put("source", source + "," + newSource);
                            customerDao.insertCustomerSource(customerOld);
                        } else {
                            //更新原来的渠道表
                            if (!oldSource.contains(newSource)) {
                                //插入
                                customerOld.put("source", oldSource + "," + newSource);
                                customerDao.insertCustomerSource(customerOld);
                            }
                        }
                    }
                    //给原来的customer加一个SOURCE_USER_ID
                    map.put("customerId", customerOld.get("customerId"));
                    LOGGER.info("三方客户信息修改参数：" + com.alibaba.fastjson.JSON.toJSONString(map));
                    customerDao.updateMapSelective(map);
                    //扣我们的积分加雅智洁积分
                    Map<String, Object> integralCustomerInfo = customerIntegralService.getCrmIntegralCustomerInfo(customerOld.get("customerId").toString());
                    Long customerScore = 0L;
                    if (integralCustomerInfo != null && !StringUtils.isEmpty(integralCustomerInfo.get("customerScore"))) {
                        customerScore = -Long.valueOf(integralCustomerInfo.get("customerScore").toString());
                    }
                    if (customerScore < 0) {
                        String msg = "系统扣除";
                        SimpleDateFormat utime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        customerIntegralService.adjustIntegralCustomerLog(customerOld.get("customerId").toString(), msg, IntegralEnums.customerScore.toString(), customerScore.toString(), IntegralEnums.other.toString(), orgId,(String) customerOld.get("sourceUserId"));
                        stringRedisTemplate.delete("home:customer_info_" + map.get("customerId").toString());
                        customerScore = -customerScore;
                        msg = "系统初始化增加";
                        customerIntegralService.addIntegralCustomerLog(customerOld.get("customerId").toString(), msg, IntegralEnums.customerScore.toString(), customerScore.toString(), IntegralEnums.other.toString(), orgId);
                    }
                    //同步用户等级
                    if(!StringUtils.isEmpty(customerOld.get("customerlevelId"))){
                        yzjRequest.alterMemberLevel(map.get("sourceUserId").toString(),"",customerOld.get("customerlevelId").toString(),orgId);
                    }
                } else {
                    LOGGER.info("三方客户信息保存参数：" + com.alibaba.fastjson.JSON.toJSONString(map));
                    customerDao.insertMapSelective(map);
                    customerInfoDao.insertMapSelective(map);
                }
            }
        } else {
            customerDao.insertMapSelective(map);
            customerInfoDao.insertMapSelective(map);
        }
        return customerId;
    }

    /**
    * @Description：添加微信小程序的用户
    * @DateTime：2021/5/12 19:22
    * @Params：
    * @Return：
    */
    @Override
    public Map<String,Object> saveWxMiniCustomer(Map<String,Object> map) {
        if (!map.containsKey("orgId") || StringUtils.isEmpty(map.get("orgId"))) {
            throw GlobalException.build("机构代码不能为空");
        }
        if (!map.containsKey("openId") || StringUtils.isEmpty(map.get("openId"))) {
            throw GlobalException.build("openId不能为空");
        }
        if (!map.containsKey("wxappid") || StringUtils.isEmpty(map.get("wxappid"))) {
            throw GlobalException.build("微信appId不能为空");
        }
        if (!StringUtils.isEmpty(map.get("province")) && !StringUtils.isEmpty(map.get("city"))) {
            map.put("customerArea", map.get("province") + "@" + map.get("city") + "@" + (map.get("region")==null ? "" : map.get("region")));
        }
        map.put("nickName",StringUtils.isEmpty(map.get("nickName")) ? "" :  map.get("nickName"));

        String orgId = map.get("orgId").toString();
        if (map.containsKey("customerId") && !StringUtils.isEmpty(map.get("customerId"))) {
            Integer customerCount = customerDao.getCustomerCountById(map);
            if (customerCount.equals(0)) {
                throw GlobalException.build("未找到对应的用户信息");
            }
            customerDao.updateBlue(map);
            customerDao.updateBlueInfo(map);
        } else {
            map.put("customerInfoId", UUID.randomUUID().toString());
            map.put("customerId", RandomCodeGenerator.getCustomerId(Constants.CUSTOMER_CODE_SOURCE_WXMINI));
            customerDao.insertBlue(map);
            customerDao.insertBlueInfo(map);
        }
        String customerId = map.get("customerId").toString();
        if (!StringUtils.isEmpty(map.get("customerPhone"))) {
            String customerPhone = map.get("customerPhone").toString();
            //需要查询是否有已绑定的用户
            Map<String, Object> crmCustomerInfo = customerDao.getOrgCustomerInfoByPhone(customerPhone, orgId);

            if (crmCustomerInfo != null) {
                //去绑定
                /* 如果有人绑定过该手机号码
                 *  1、判断绑过手机号的用户的来源是否跟当前的渠道不一致，如果不一致则加上当前渠道，并修改最后编辑时间
                 *  2、切换账号登录（登录为对方的账号信息），需要在关联表修改当前的openid token对应的cid
                 *  3、更新当前redis及session的登录信息
                 */

                // region 第一步修改将要绑定用户的多渠道信息

                // 被绑用户多渠道
                Map<String, Object> otherCustomerSourceInfo = personalCenterDao.getCustomerSourceByCustomerId(crmCustomerInfo.get("customerId").toString());
                // 被绑用户来源
                Integer otherCustomerSourceI = (Integer) crmCustomerInfo.get("customerSourceChannel");
                String otherCustomerSource = String.valueOf(otherCustomerSourceI);

                // 绑定用户来源
                String customerSource = "8";

                //将要关联的渠道Map
                Map<String, Object> sources = new HashMap<>();
                sources.put("orgId", map.get("orgId").toString());
                String newSource = "";
                // 来源不同 需要关联渠道
                if (!otherCustomerSource.equals(customerSource)) {
                    // 被绑用户来源增加
                    sources.put("customerId", crmCustomerInfo.get("customerId").toString());
                    if (StringUtils.isEmpty(otherCustomerSourceInfo)) {
                        newSource = otherCustomerSource + "," + customerSource;
                    } else {
                        // 已经是多渠道 是否包含 customerSource
                        if (!(otherCustomerSourceInfo.get("customerSourceChannel").toString().contains(customerSource))) {
                            newSource = otherCustomerSourceInfo.get("customerSourceChannel").toString() + "," + customerSource;
                        }
                    }
                }
                //判断如果需要更新多渠道信息，则更新该用户的渠道信息
                if (!StringUtils.isEmpty(newSource)) {
                    sources.put("customerSource", newSource);
                    personalCenterDao.insertCustomerSource(sources);
                }
                // endregion

                // region 第二步修改当前登录信息表中对应公众号OpenId对应的 本系统用户Cid信息
                Map<String, Object> loginCustomerInfo = new HashMap<>();
                //新的绑定的手机号码
                loginCustomerInfo.put("phone", map.get("customerPhone").toString());
                //当前登录用户及（当前微信客户端登录的openid，微信公众号）
                loginCustomerInfo.put("openId", map.get("openId"));
                //当前登录用户的微信公众号
                loginCustomerInfo.put("token", map.get("wxappid"));
                //将要切换的用户的我们系统中的CID
                loginCustomerInfo.put("customerId", crmCustomerInfo.get("customerId"));
                //该字段为预留的ID
                loginCustomerInfo.put("appOpenId", "");
                loginCustomerInfo.put("orgId", orgId);
                personalCenterDao.addBusiPhone(loginCustomerInfo);
            } else {
                //电话号码未被别人绑定过直接绑定电话
                customerDao.bindCustomerPhone(map.get("customerId").toString(), map.get("customerPhone").toString());
            }
            //异步更新等级
            customerIntegralService.upateCustomerLevel(customerId, orgId, null, null);
            stringRedisTemplate.delete("home:customer_info_" + map.get("customerId").toString());
            String openId = "";
            if (!StringUtils.isEmpty(map.get("openId"))) {
                openId = map.get("openId").toString();
            }
            String key = MD5.encode(orgId + openId);

            if (crmCustomerInfo == null) {
                stringRedisTemplate.delete("login:" + key);
            } else {
                //region 登录信息修改
                Map h5Map = new HashMap();
                Integer payMode = userService.getPayMode(orgId);
                h5Map.put("customerId", crmCustomerInfo.get("customerId"));
                h5Map.put("cover", crmCustomerInfo.get("customerAvatar"));
                h5Map.put("gender", crmCustomerInfo.get("gender"));
                h5Map.put("payMode", payMode);
                h5Map.put("globalOpenid", openId);
                h5Map.put("openid", crmCustomerInfo.get("openId"));
                h5Map.put("orgId", orgId);
                h5Map.put("token", crmCustomerInfo.get("token"));
                h5Map.put("nickname", crmCustomerInfo.get("customerName") == null ? " " : crmCustomerInfo.get("customerName"));
                //endregion
                Integer isVip = vipCustomerLogService.getIsVip(crmCustomerInfo.get("customerId").toString(), orgId);
                h5Map.put("isVip", isVip);
                //更新缓存
                String h5User = com.alibaba.fastjson.JSON.toJSONString(h5Map, SerializerFeature.WriteMapNullValue);
                stringRedisTemplate.opsForValue().set("login:" + key, h5User, 15, TimeUnit.MINUTES);
                //endregion

                //region 返回的用户信息为切换后的人的用户信息
                map.put("customerId", crmCustomerInfo.get("customerId"));
                map.put("nickName", crmCustomerInfo.get("customerName"));
                map.put("userIcon", crmCustomerInfo.get("customerAvatar"));
                map.put("gender", crmCustomerInfo.get("gender"));
                map.put("customerBirth", crmCustomerInfo.get("customerBirth"));
                map.put("customerPhone",customerPhone);
                map.put("province", "");
                map.put("city", "");
                map.put("region", "");
                if (!StringUtils.isEmpty(crmCustomerInfo.get("customerArea"))) {
                    String[] areaSplit = crmCustomerInfo.get("customerArea").toString().split("@");
                    map.put("province", areaSplit.length > 0 ? areaSplit[0] : "");
                    map.put("city", areaSplit.length > 1 ? areaSplit[1] : "");
                    map.put("region", areaSplit.length > 2 ? areaSplit[2] : "");
                }
                //endregion
            }
            stringRedisTemplate.delete("home:customer_info_" + map.get("customerId").toString());
        }
        //异步更新等级
        customerIntegralService.upateCustomerLevel(customerId, orgId, null, null);
        stringRedisTemplate.delete("home:customer_info_" + map.get("customerId").toString());
        return map;
    }


    @Override
    public void updateBindCustomerId(UpdateBindCustomerPo updateBindCustomerPo) {
        this.personalCenterDao.changeLoginCustomer(updateBindCustomerPo);
    }

    /**
     * 给用户打标签
     *
     * @param customerId
     * @param idpOrgId
     * @param idpLabels
     */
    private void saveLabels(final String customerId, final String idpOrgId, List idpLabels) {
        if (idpLabels != null && !idpLabels.isEmpty()) {
            //  更新标签表标签 insert ignore into
            List<Label> labels = (List<Label>) idpLabels.stream()
                    .filter(a -> !StringUtils.isEmpty(a))
                    .map(i -> {
                        Label l = new Label();
                        l.setLabelId(UUID.randomUUID().toString());
                        l.setLabelName(i.toString());
                        l.setLabelType(Constants.LABEL_TYPE_IDP);
                        l.setLabelDescription("");
                        l.setOrgId(idpOrgId);
                        return l;
                    })
                    .distinct().collect(Collectors.toList());

            if (labels != null && !labels.isEmpty()) {
                LOGGER.info("更新标签库");
                Integer addLabels = syncDao.addLabels(labels);
            }
            //  更新用户idp标签 （预先设置唯一索引）
            List<Label> idpTypeLabels = syncDao.findLabelsByType(Constants.LABEL_TYPE_IDP, idpOrgId);
            Integer deleteCustomerLabels = syncDao.deleteCustomerLabels(customerId, Constants.LABEL_TYPE_IDP);

            idpTypeLabels = idpTypeLabels.stream().filter(i -> idpLabels.contains(i.getLabelName())).collect(Collectors.toList());
            List<LabelRelation> relations = idpTypeLabels.stream()
                    .map(i -> {
                        LabelRelation relation = new LabelRelation();
                        relation.setCustomerId(customerId);
                        relation.setLabelId(i.getLabelId());
                        return relation;
                    }).collect(Collectors.toList());

            if (relations != null && !relations.isEmpty()) {
                LOGGER.info("给用户[{}]添加标签", customerId);
                Integer addLabelsToCustomer = syncDao.addLabelsToCustomer(relations);
            }
        } else {
            LOGGER.info("删除用户[{}]的标签", customerId);
            //  删除idp相关标签
            Integer deleteCustomerLabels = syncDao.deleteCustomerLabels(customerId, Constants.LABEL_TYPE_IDP);
        }
    }

    /**
     * 匹配
     * 1.idp键名 2.数据库字典配置的idp键名描述信息 3.idp键值
     *
     * @param key
     * @param idpName
     * @param names
     * @param attributes
     */
    private void matchName(String key, String idpName, Set<Object> names, List<KeyNameValue> attributes) {
        if (!StringUtils.isEmpty(idpName) && names.contains(key)) {
            String desc = (String) stringRedisTemplate.opsForHash().get(RedisConstants.CRM_IDP_NAME_DICT, key);
            attributes.add(new KeyNameValue(key, desc, new String[]{idpName}));
        }
    }

    private String getOrgCodeByToken(String token) {
        if (StringUtils.isEmpty(token)) {
            return "";
        }
        try {
            WxOrgInfo wxOrgInfo = customerBindService.getOrgInfo(
                    new BindUserDto(null, null, null, null, token, null), true);
            String orgCode = wxOrgInfo != null ? wxOrgInfo.getOrgcode() : "";
            return orgCode;
        } catch (IOException | URISyntaxException e) {
            e.printStackTrace();
        }
        return "";
    }
}
